import psutil, time, os
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from traceback import format_exc

"""
2018.10.26
预计简化程序，
    简化字符串形式，"i min [rate][use_in_a_min][use_all_min]"
    简化open_write的调用，组织好字符串后统一写入文件
    简化程序结构，重构函数主体
2019-10-16 -> 已经不知道都写的啥了。 注释很重要啊！
2019-10-17 -> 把 每分钟的数据写入文件。 -
2019-10-18 -> 加入邮件模块， 可以每小时发送邮件-Form:1491311784@qq.com To:lee-cq@icloud.com
2019-10-20 -> 重构 邮件发送 内容。刷新输出实时速率
2019-10-26 -> 添加 chooseDisplay_Network_speed
"""
# ------------- 基本参数 ---------------------------------------------------
f_Log = './Log_test.txt'
f_logError = './_sup/Log_DataUse_Error.log'
Sleep_Time, for_interval = 60, 60
nowTime = time.strftime("%Y-%m-%d %H:%M", time.localtime())  # Now Time
chooseDisplay_Network_speed = False                              # True. 显示  0. 不显示
# --------------------------------------------------------------------------


def Traceback():
    with open(f_logError, mode='a', encoding='utf8') as f_e:
        f_e.write(f'**********{nowTime}**********\n{format_exc()}\n\n')


def send_email(title, msg):
    # 第三方 SMTP 服务
    # emInfo = format_info(info_email)              # 直接使用字符串，注释文件读入--没有函数
    # print(emInfo)
    receiver = 'lee_cq@icloud.com'  # 收件人 (List or Str)
    senderName = f'{time.strftime("%H:%M", time.localtime())}的流量'
    sender = '1491311784@qq.com'  # 发件人
    mailHost = "smtp.qq.com"  # SMTP 服务器
    mailUser = '1491311784@qq.com'  # User
    mailPasswd = "gfpvtffnkoyigjhb"  # Passwd

    message = MIMEText(msg, 'plain', 'utf-8')  # 创建消息实例 内容 格式（plain，html） 编码
    message['Subject'] = Header(title, 'utf-8')  # 消息的 主题或标题
    message['from'] = f'{senderName}<{sender}>'  # 发件人
    message['to'] = receiver  # 收件人

    try:
        smtpObj = smtplib.SMTP(host=mailHost)  # 建立SMTP链接的实例, (从3.7开始实例化需要指定Host)
        smtpObj.connect(mailHost, 25)  # 25 为 SMTP 端口号 - 链接到SMTP的服务器
        smtpObj.login(mailUser, mailPasswd)  # 登录用户
        smtpObj.sendmail(sender, receiver, message.as_string())  # 发送邮件-发件人-收件人- 消息对象
        print("邮件发送成功")
        return 0, receiver
    except smtplib.SMTPConnectError and smtplib.SMTPDataError:
        print("Error: 无法发送邮件")
        # remove(f_ipv4)
        Traceback()
        return -1, receiver

# -------------------------------------------------------------------------------------


def network_speed(n):
    """import psutil，time
    Network speed. Unit = ** Kb/s"""
    sent_a = psutil.net_io_counters().bytes_sent  # 获取某一时间点的数据量 -.发送的-
    recv_a = psutil.net_io_counters().bytes_recv  # 获取某一时间点的数据量 -.接受的-
    time.sleep(1)
    sent_b = psutil.net_io_counters().bytes_sent
    recv_b = psutil.net_io_counters().bytes_recv
    print('\r' + f"[{cycle-1} min {n} s]".ljust(10) + f"上行{round((sent_b - sent_a)/1024, 2)}kb/s，下行{round((recv_b - recv_a)/1024, 2)}kb/s",
          end='', flush=True)
    return recv_b - recv_a


def count_min(data_b=(0, 0), data_e=(0, 0)):
    """ data_b 开始数据  data_e 结束数据"""
    if data_e[0] == 0 or data_b[1] is 0: return 0, 0
    return round(((data_e[0] - data_b[0]) / (60 * 1024)), 2), round(((data_e[1] - data_b[1]) / (60 * 1024)), 2)


def network_amount_now() -> object:
    """Network amount. Unit = ** Kb; 得到当前时间的数据量"""
    _net = psutil.net_io_counters()
    return _net.bytes_sent, _net.bytes_recv


def network_minute():
    """
    计算60s内的网速，流量
    :return: str(up_rate, down_rate, up_use, down_use)
    """
    first = network_amount_now()
    if chooseDisplay_Network_speed is True:
        for i in range(Sleep_Time): network_speed(i)
    else: time.sleep(Sleep_Time)
    print('\r', flush=True, end='')
    last = network_amount_now()

    # round(一个浮点数, 保留浮点数的位数) 返回四舍五入的位数
    sent_use_level = round(((last[0] - first[0]) / (1024 * 1024)), 3)  # 计算这一分钟的使用量（单位：MB）
    recv_use_level = round(((last[1] - first[1]) / (1024 * 1024)), 3)
    sent_rate = round(((last[0] - first[0]) / (60 * 1024)), 2)  # 计算 1min 内 的平均速度 （单位：kb/s）
    recv_rate = round(((last[1] - first[1]) / (60 * 1024)), 2)
    result_rate = f"[up_rate：{sent_rate}kb/s down_rate：{recv_rate}kb/s]"
    result_use = f"[up_use:{sent_use_level}Mb down_use:{recv_use_level}Mb]"
    result = result_rate + result_use
    return result.ljust(76)


def main():
    os.system(f'title 正在统计从{time.strftime("%Y-%m-%d  %H:%M:%S", time.localtime())}开始的流量')
    print(f'正在统计从{time.strftime("%Y-%m-%d  %H:%M:%S", time.localtime())}开始的流量')
    # 初始化写入文件
    with open(f_Log, "a", encoding="utf-8") as log1:
        log1.write("*" * 15 + f"开始时间：{time.strftime('%Y-%m-%d  %H:%M:%S', time.localtime())}" + "*" * 15 + '\n')

    begin = network_amount_now()
    global cycle
    cycle = 1
    # -----Main Cycle---------------------------------------------------------------
    while True:
        hourBegin = network_amount_now()
        # ------------------------------------------------------------------------------
        for i in range(for_interval):
            # 每分钟写入一次网速
            _str = f'{cycle}min'.ljust(7) + f'[{time.strftime("%H:%M", time.localtime())}]'
            _str += network_minute()  # network_minute() 返回字符串
            counter = count_min(begin, network_amount_now())
            _str += f"All_Sent:{counter[0]}Mb({round(counter[0] / 1024, 4)}Gb)".ljust(30)
            _str += f"All_Recv:{counter[1]}Mb({round(counter[1] / 1024, 4)}Gb)"
            print(_str)
            with open(f_Log, "a", encoding="utf-8")as f:
                f.write(_str + '\n')
            cycle += 1

        # ------------ send mail every Hour -------------------------------------
        hourEnd = network_amount_now()
        hourQuantitySent = (hourEnd[0] - hourBegin[0]) / 1024           # 单位  kb
        hourQuantityRecv = (hourEnd[1] - hourBegin[1]) / 1024
        hourSpeedSent = round((hourQuantitySent / (3600 * 1024)), 2)    # 单位 kb/s
        hourSpeedRecv = round((hourQuantityRecv / (3600 * 1024)), 2)
        # ------------ send mail Global -----------------------------------------
        QuantitySent = (hourEnd[0] - begin[0]) / 1024                   # 单位  kb
        QuantityRecv = (hourEnd[1] - begin[1]) / 1024
        SpeedSent = round((QuantitySent / (cycle * 60 * 1024)), 2)      # 单位 kb/s
        SpeedRecv = round((QuantityRecv / (cycle * 60 * 1024)), 2)

        # ---send mail -----
        mailTitle = f'{time.strftime("%Y-%m-%d %H:%M", time.localtime())}前一小时的流量使用情况（持续时间：{cycle-1}min）'
        mailMsg = '这一小时中的:\n'
        mailMsg += f'Sent Speed:' + f'{hourSpeedSent}Kb/s'.ljust(10) + f'\nRecv Speed:' + f'{hourSpeedRecv}Kb/s'.ljust(10) + '\n'
        mailMsg += f'发送量:' + f'{round(hourQuantitySent / 1024, 3)}Mb ({round(hourQuantitySent / (1024 * 1024), 3)}Gb)'.ljust(30) + '\n'
        mailMsg += f'接收量:' + f'{round(hourQuantityRecv / 1024, 3)}Mb ({round(hourQuantityRecv / (1024 * 1024),3)}Gb)'.ljust(30) + '\n'
        mailMsg += '--------------------------------\n'
        mailMsg += f'从{nowTime}开始的{cycle-1}min的总数据：\n'
        mailMsg += f'Sent Speed:' + f'{SpeedSent}Kb/s'.ljust(10) + f'\nRecv Speed:' + f'{SpeedRecv}Kb/s'.ljust(10) + '\n'
        mailMsg += f'发送量:' + f'{round(QuantitySent / 1024, 3)}Mb ({round(QuantitySent / (1024 * 1024), 3)}Gb)'.ljust(30) + '\n'
        mailMsg += f'接收量:' + f'{round(QuantityRecv / 1024, 3)}Mb ({round(QuantityRecv / (1024 * 1024), 3)}Gb)'.ljust(30) + '\n'
        send_email(mailTitle, mailMsg)


if __name__ == "__main__":
    main()
